/**
 * @fileoverview Dx
 * this loads core Dx library
 */

///////////////////////////////////////////////////////////////////////////////
// Setup and defaults
///////////////////////////////////////////////////////////////////////////////

// initial setup
(function() {

   var GLOBAL = this;

   // setup GLOBAL variable
   if (!('Dx' in GLOBAL)) {

      GLOBAL.Dx = { GLOBAL: GLOBAL };

   }

}).call(null);

/**
 * configure Dx
 */
(function(D) {

   var isEnumerable = Object.prototype.propertyIsEnumerable;

   var candidates = [
         'hasOwnProperty',
         'valueOf',
         'isPrototypeOf',
         'propertyIsEnumerable',
         'toLocaleString',
         'toString',
         'constructor'
      ];

   var n, l, sample;

   for (sample = {}, l = candidates.length; l--;) {

      n = candidates[l];

      sample[n] = 1;

      if (isEnumerable.call(sample, n)) {

         candidates.splice(l, 1);

      }

      delete sample[n];

   }

   D.nonEnumerables = candidates;

})(Dx);

/**
 * iterates the Object (target)
 * @param {*} target the Object to iterate
 * @param {Function} callback the callback Function to call for iterated items
 * @param {*} scope the scope of the callback Function when invoked.
 * @return {*} the target parameter
 */
Dx.each = function(target, callback, scope) {

   var O = Object.prototype;

   var enums = Dx.nonEnumerables;

   var n, l, hasOwn;

   for (n in target) {

      if (callback.call(scope, n, target[n], target) === false) {

         break;

      }

   }

   if (enums && target instanceof O.constructor) {

      hasOwn = O.hasOwnProperty;

      for (n, l = enums.length; l--;) {

         n = enums[l];

         if (target[n] === O[n] && !hasOwn.call(target, n)) {

            continue;

         }

         if (callback.call(scope, n, target[n], target) === false) {

            break;

         }

      }

   }

   return target;

};


Dx.each(

/** @lends Dx */ {

   nts: Object.prototype.toString,

///////////////////////////////////////////////////////////////////////////////
// Native Object Manipulation
///////////////////////////////////////////////////////////////////////////////

/**
 * Assign new properties to Object (target)
 * @param {*} target the target Object
 * @param {Object} properties the new properties to assign to the target Object
 * @param {Object=} defaults the defaults properties to assign to target
 *    before assigning the properties
 * @return {*} the target (Object)
 */
   assign: function(target, properties, defaults) {

      var D = Dx,

         callback = D._callback_assign;

      if (defaults) {

         D.each(defaults, callback, target);

      }

      D.each(properties, callback, target);

      return target;

   },

/**
 * callback for iterating Native objects when calling Dx.assign();
 *
 * @this {*} target object
 * @param {String} name property name
 * @param {*} value new property value
 * @param {Object} source the source object iterated
 */
   _callback_assign: function(name, value, source) {

      this[name] = value;

   },


/**
 * clears the properties of an object
 * @param {Object} obj target object
 * @return {Object} the target object that has its properties cleared.
 */
   clear: function(obj) {

      var D = Dx;

      D.each(obj, D._callback_clearObject);

      return obj;

   },

/**
 * callback for iterating Native objects when calling Dx.clear();
 *
 * @this {*} target object
 * @param {String} name property name
 * @param {*} value new property value
 * @param {Object} source the source object iterated
 */
   _callback_clear: function(name, value, source) {

      delete source[name];

   },

///////////////////////////////////////////////////////////////////////////////
// Object Type Inspection Methods
///////////////////////////////////////////////////////////////////////////////

/**
 * Checks if o is Object
 * @param {*} o the subject
 * @param {Boolean=} checkIfNativeObject true if also check if o is
 *    a native Javascript Object. default is true.
 * @return {Boolean} true if o subject is an Object
 */
   isObject: function(o, checkIfNativeObject) {

      var isObject = this.nts.call(o) == '[object Object]';

      return checkIfNativeObject === false ?

         (isObject || typeof o == 'object') :

            (o instanceof Object && isObject);

   },

/**
 * Checks if o is String
 * @param {*} o the subject
 * @param {Boolean=} checkIfNotEmpty true if also check if o is
 *    a native Javascript Object
 * @return {Boolean} true if o subject is a String
 */
   isString: function(o, checkIfNotEmpty) {

      return typeof o == 'string' &&

         (!checkIfNotEmpty || !!o);

   },

/**
 * Checks if o is Number
 * @param {*} o the subject
 * @return {Boolean} true if o subject is a Number
 */
   isNumber: function(o) {

      return typeof o == 'number' && isFinite(o);

   },

/**
 * Checks if o is Scalar or one of the following types:
 *    String, Number, or Boolean (if second parameter is true)
 * @param {*} o the subject
 * @param {Boolean=} includeBoolean if include Boolean as scalar type
 *    default is false
 * @return {Boolean} true if o subject is a Scalar
 */
   isScalar: function(o, includeBoolean) {

      var type = this.nts.call(o);

      return type == '[object String]' || isFinite(o) ||

         (!!includeBoolean && type == '[object Boolean]');

   },

   is: function(type, o) {

      return this.nts.call(o) == '[object ' + type + ']';

   }


}, function(name, value) { this[name] = value; }, Dx);
